#include "game.h"
#include "ui_game.h"
#include<QPushButton>
#include<QRect>
#include<QLabel>
#include<QButtonGroup>
#include<QRadioButton>
#include<bits/stdc++.h>
#include<QPaintEvent>
#include<QPainter>
#include<QBrush>
#include<QPen>
#include<QColor>
#include<QMessageBox>
#include<QMouseEvent>
using namespace std;

Game::Game(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::Game)
{
    ui->setupUi(this);

    //开始页面
    setWindowTitle("五子棋");//标题
    setMinimumSize(1000,800);
    setMaximumSize(1000,800);//画面大小

    QPushButton *button_s=new QPushButton(this);
    button_s->setStyleSheet("font:Bold;font-size:36px;color:yellow;background-color:rgb(105,105,105);border:2px;border-radius:10px;padding:2px 4px;");
    button_s->setGeometry(QRect(780,100,200,50));
    button_s->setText("游戏模式");//游戏模式按钮

    type=1;
    select=new QButtonGroup(this);
    QRadioButton *PVC= new QRadioButton(tr("人机对战"),this);
    select->addButton(PVC,1);
    PVC->setStyleSheet("font:Bold;font-size:36px;color:black;");
    PVC->setGeometry(825,200,100,30);
    connect(PVC,SIGNAL(clicked()),this,SLOT(selectradio()));//人机模式
    QRadioButton *PVP= new QRadioButton(tr("人人对战"),this);
    select->addButton(PVP,2);
    PVP->setStyleSheet("font:Bold;font-size:36px;color:black;");
    PVP->setGeometry(825,270,100,30);
    connect(PVP,SIGNAL(clicked()),this,SLOT(selectradio()));//人人模式
    PVC->setChecked(true);//初始为人机

    flag=0;
    button =new QPushButton(this);
    button->setStyleSheet("font:Bold;font-size:36px;color:white;background-color:rgb(30,144,255);border:2px;border-radius:10px;padding:2px 4px;");
    button->setGeometry(QRect(800,390,170,50));
    button->setText("开始");
    connect(button,SIGNAL(clicked()),this,SLOT(open()));//开始结束按钮

    while(!sta.empty())sta.pop();
    QPushButton *back_button = new QPushButton(this);
    back_button->setStyleSheet(("QPushButton{font:Bold;font-size:30px;color:white;background-color:rgb(191, 62, 255);border:2px ;border-radius:10px;padding:2px 4px;}""QPushButton:hover{color:white;background-color:rgb(178, 58, 238);}""QPushButton:pressed{color:white;background-color:rgb(154, 50, 205);padding-left:3px;padding-top:3px;"));
    back_button->setGeometry(QRect(830,520,110,40));
    back_button->setText("悔棋");
    connect(back_button,SIGNAL(clicked()),this,SLOT(back()));

    //结束
    setMouseTracking(true);

    lock=1;
    memset(chessboard,0,sizeof(chessboard));
}

//游戏模式选择
void Game::selectradio(){
    switch(select->checkedId()){
    case 1:
        type=1;
        break;
    case 2:
        type=2;
        break;
    }
}

//开始结束按钮
 void Game::open(){
    if(flag==0){
        player=0;
        lock=0;
        current1=-100;
        current2=-100;
        move1=-100;
        move2=-100;
        while(!sta.empty())sta.pop();
        memset(chessboard,0,sizeof(chessboard));
        button->setText("结束");
        button->setStyleSheet(("font:Bold;font-size:36px;color:white;background-color:rgb(255,0,0);border:2px ;border-radius:10px;padding:2px 4px;"));
    }
    else{
        button->setText("开始");
        button->setStyleSheet(("font:Bold;font-size:36px;color:white;background-color: rgb(30, 144, 255);border:2px ;border-radius:10px;padding:2px 4px;"));
        lock=1;
        memset(chessboard,0,sizeof(chessboard));
        update();
    }
    flag=!flag;
}

//悔棋按钮
 void Game::back(){
    if(sta.empty()||flag==0)
        return;
    int num=1;
    if(type==1)num++;
    if(winner=="YOU"&&lock==1)num--;
    for(int i=0;i<num;++i){
        chessboard[sta.top().x()][sta.top().y()]=0;
        sta.pop();
        player--;
    }
    if(!sta.empty()){
        current1=sta.top().x();
        current2=sta.top().y();
    }
    else{
        current1=-100;
        current2=-100;
    }
    lock=0;
    update();
}

//绘图
void Game::paintEvent(QPaintEvent *){
    QPainter p(this);
    p.setRenderHint(QPainter::Antialiasing,true);

    //棋盘
    QBrush brush;
    brush.setColor(QColor(213,176,141));
    brush.setStyle(Qt::SolidPattern);
    p.setBrush(brush);
    QPen pen=p.pen();
    p.setPen(pen);
    p.drawRect(30,30,740,740);
    pen.setColor(Qt::black);
    pen.setWidth(1);
    p.setPen(pen);
    for(int i=0;i<15;++i){
        p.drawLine(50,50+i*50,750,50+i*50);
        p.drawLine(50+i*50,50,50+i*50,750);
    }
    brush.setColor(Qt::black);
    p.setBrush(brush);
    p.drawRect(195,195,10,10);
    p.drawRect(595,195,10,10);
    p.drawRect(195,595,10,10);
    p.drawRect(595,595,10,10);
    p.drawRect(395,395,10,10);

    //棋子
    brush.setStyle(Qt::SolidPattern);
    for(int i=0;i<15;++i){
        for(int j=0;j<15;++j){
            if(chessboard[i][j]==1){
                brush.setColor(Qt::black);
                p.setBrush(brush);
                p.drawEllipse(QPoint(i*50+50,j*50+50),20,20);
            }
            else if(chessboard[i][j]==2){
                brush.setColor(Qt::white);
                p.setPen(Qt::NoPen);
                p.setBrush(brush);
                p.drawEllipse(QPoint(i*50+50,j*50+50),20,20);
            }
        }
    }

    //游戏过程
    if(!flag)
        return;
    pen.setColor(Qt::red);
    pen.setWidth(1);
    p.setPen(pen);
    p.setBrush(Qt::NoBrush);
    p.drawRect(current1*50+50-23,current2*50+50-23,46,46);//上一颗棋子的红框
    if(lock)return;

}

//判断输赢
void Game::win(int x, int y){
    QPoint p(x,y);
    if(iswin(p)){
        lock=1;
        if(type==1){
            if(chessboard[x][y]==1)
                winner="YOU";
            else
                winner="AI";
        }
        else{
            if(chessboard[x][y]==1)
                winner="BLACK";
            else
                winner="WHITE";
        }
        QMessageBox::information(NULL,"GAME OVER",winner+" WIN",QMessageBox::Ok);
    }
}

//是否赢
int Game::iswin(QPoint p){
    int dir_cnt[8]={0};
    memset(dir_cnt,0,sizeof(dir_cnt));
    for(int i=0;i<8;++i){
        for(int j=1;;++j){
            if(getpoint(p,i,j)!=chessboard[p.x()][p.y()])
                break;
            dir_cnt[i]++;
        }
    }
    for(int i=0;i<4;++i){
        if(dir_cnt[i]+dir_cnt[i+4]+1>=5){
            return 1;
        }
    }
    return 0;
}

//棋子位移
int Game::getpoint(QPoint p, int direction, int offset){
    int y=p.y();
    int x=p.x();
    x=x+offset*m_direction[direction].x();
    y=y+offset*m_direction[direction].y();
    if(y<0||x<0||x>=15||y>=15){
        return -100;
    }
    return chessboard[x][y];
}

//鼠标移动
void Game::mouseMoveEvent(QMouseEvent *e){
    move1=(e->x()+25)/50-1;
    move2=(e->y()+25)/50-1;
    update();
}

//下棋
void Game::mousePressEvent(QMouseEvent *e){
    if(lock)
        return;
    if(!(type==1&&(player&1))){
        persontime(e);
        if(lock==0&&type==1&&(player&1)){
            AI_time();
        }
    }
}

//人下棋
void Game::persontime(QMouseEvent *e){
    int x,y;
    if((e->x()>=25&&e->x()<=775)&&(e->y()>=25&&e->y()<=775)){
        x=(e->x()+25)/50-1;
        y=(e->y()+25)/50-1;
        updatechessboard(x,y);
    }
}

//机下棋
void Game::AI_time(){
    QPoint bestattack;
    QPoint bestdefend;
    int max1=0;
    int max2=0;
    //最好进攻的地方
    for(int i=0;i<15;++i){
        for(int j=0;j<15;++j){
            QPoint now(i,j);
            if(chessboard[now.x()][now.y()]!=0)
                continue;
            int value=assess(now,1);
            if(max1<value){
                max1=value;
                bestattack=now;
            }
        }
    }
    //最应防守的地方
    for(int i=0;i<15;++i){
        for(int j=0;j<15;++j){
            QPoint now(i,j);
            if(chessboard[now.x()][now.y()]!=0)
                continue;
            int value =assess(now,0);
            if(max2<value){
                max2=value;
                bestdefend=now;
            }
        }
    }
    if(max1>=max2)
        updatechessboard(bestattack.x(),bestattack.y());
    else
        updatechessboard(bestdefend.x(),bestdefend.y());
}

//更新棋盘
void Game::updatechessboard(int x, int y){
    if(!chessboard[x][y]){
        chessboard[x][y]=player++ %2+1;
        current1=x;
        current2=y;
        QPoint p(x,y);
        sta.push(p);
        update();
        win(x,y);
    }
}

//评分
int Game::assess(QPoint now, int m){
    int value=0;
    int riv=!m;
    m+=1;
    riv+=1;
    int empty =0;
    int boundary =0;
    int cntlive2=0;//活2
    //要经过八个方向
    //连着5个>活4>死4>活3>活2>死3>死2>其他阵型
    for(int i=0;i<8;++i){
        //活4
        if(getpoint(now,i,1)==m && getpoint(now,i,2)==m && getpoint(now,i,3)== m&&getpoint(now,i,4)== m&&getpoint(now,i,5)==empty){
            value += 300000;
            if(m==1)
                value-=500;
            continue;
        }
        //死4
        //(1)
        if(getpoint(now,i,1)==m&&getpoint(now,i,2)==m&&getpoint(now,i,3)==m&&getpoint(now,i,4)==m&&(getpoint(now,i,5)==riv||getpoint(now,i,5)==boundary)){
            value +=250000;
            if(m==1)
                value-=500;
            continue;
        }
        //(2)
        if(getpoint(now,i,-1)==m&&getpoint(now,i,1)==m&&getpoint(now,i,2)==m&&getpoint(now,i,3)==m){
            value +=240000;
            if(m==1)value-=500;
            continue;
        }
        //(3)
        if(getpoint(now,i,-2)==m&&getpoint(now,i,-1)==m&&getpoint(now,i,1)==m&&getpoint(now,i,2)==m){
            value +=230000;
            if(m==1)
                value-=500;
            continue;
        }
        //活3
        //(1)
        if(getpoint(now,i,-1)==m&&getpoint(now,i,-2)==m&&getpoint(now,i,-3)==m){
            if(getpoint(now,i,1)==empty){
                value+=750;
                if(getpoint(now,i,-4)==empty){
                    value+=3150;
                    if(m==1)
                        value-=500;
                }
            }
            if(getpoint(now,i,-4)==empty&&(getpoint(now,i,1)==riv||getpoint(now,i,1)==boundary)){
                value+=500;
            }
            continue;
        }
        //(2)
        if(getpoint(now,i,-1)==empty&&getpoint(now,i,-2)==m&&getpoint(now,i,-3)==m&&getpoint(now,i,-4)==m){
            value+=350;
            continue;
        }
        //死3
        if(getpoint(now,i,-1)==m&&getpoint(now,i,-2)==m&&getpoint(now,i,1)==m){
            value+=600;
            if(getpoint(now,i,-3)==empty&&getpoint(now,i,2)==empty){
                value+=3150;
                continue;
            }
            if((getpoint(now,i,-3)==riv||getpoint(now,i,-3)==boundary)&&(getpoint(now,i,2)==riv||getpoint(now,i,2)==boundary)){
                continue;
            }
            else{
                value+=700;
                continue;
            }
        }
        //活2
        if(getpoint(now,i,-1)==m&&getpoint(now,i,-2)==m&&getpoint(now,i,-3)!=riv&&getpoint(now,i,1)!=riv)
            cntlive2++;

        //若周围我方棋子数目较多，适当增加权值
        int surround=0;
        for(int k=-4;k<=0;++k){
            int temp;
            for(int l=0;l<=4;++l){
                if(getpoint(now,i,k+l)==m)
                    temp++;
                else if((getpoint(now,i,k+1)==riv||getpoint(now,i,k+1)==boundary)){
                    temp=0;
                    break;
                }
            }
            surround+=temp;
        }
        value+=surround*15;
    }
    if(cntlive2>=2){
        value+=3000;
        if(m==1)
            value-=100;
    }
    return value;

}

Game::~Game()
{
    delete ui;
}
